﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;


//Hoặc sử dụng Handle cho textbox truyền vào
public class WaterMarkTextBox_Handle
{
    #region Fields

    #region Protected Fields

    protected string _waterMarkText = "Default Watermark..."; //The watermark text
    protected Color _waterMarkColor; //Color of the watermark when the control does not have focus
    protected Color _waterMarkActiveColor; //Color of the watermark when the control has focus
    protected int _waterMarkPadding = 2;

    #endregion

    #region Private Fields
    private TextBox txt;
    private Panel waterMarkContainer; //Container to hold the watermark
    private Font waterMarkFont; //Font of the watermark
    private SolidBrush waterMarkBrush; //Brush for the watermark

    #endregion

    #endregion

    #region Constructors

    public WaterMarkTextBox_Handle(TextBox txt, bool AlwaysDisplay = false)
    {
        this.txt = txt;
        this.WaterMarkAlwaysDisplay = AlwaysDisplay;
        Initialize();
    }

    #endregion

    #region Private Methods

    /// <summary>
    /// Initializes watermark properties and adds CtextBox events
    /// </summary>
    private void Initialize()
    {
        //Sets some default values to the watermark properties
        _waterMarkColor = Color.LightGray;
        _waterMarkActiveColor = Color.Gray;
        waterMarkFont = txt.Font;
        waterMarkBrush = new SolidBrush(_waterMarkActiveColor);
        waterMarkContainer = null;

        //Draw the watermark, so we can see it in design time
        DrawWaterMark();

        //Eventhandlers which contains function calls. 
        //Either to draw or to remove the watermark
        txt.Enter += new EventHandler(ThisHasFocus);
        txt.Leave += new EventHandler(ThisWasLeaved);
        txt.TextChanged += new EventHandler(ThisTextChanged);
        txt.Validated += new EventHandler(txt_Validated);
    }

    /// <summary>
    /// Removes the watermark if it should and  it not be 'always display'
    /// </summary>
    private void RemoveWaterMark()
    {
        if (waterMarkContainer != null)
        {
            txt.Controls.Remove(waterMarkContainer);
            waterMarkContainer = null;
            //txt.SetFocus_SelectAll();
        }
    }

    /// <summary>
    /// Draws the watermark if the text length is 0
    /// </summary>
    Label lbl;
    private void DrawWaterMark()
    {
        if ((this.waterMarkContainer == null && txt.TextLength <= 0) || WaterMarkAlwaysDisplay)
        {
            waterMarkContainer = new Panel(); // Creates the new panel instance

            if (WaterMarkAlwaysDisplay)
            {
                lbl = new Label();
                lbl.Text = this._waterMarkText;
                lbl.ForeColor = Color.Transparent;
                waterMarkContainer.Controls.Add(lbl);
            }
            waterMarkContainer.Paint += new PaintEventHandler(waterMarkContainer_Paint);
            waterMarkContainer.Invalidate();
            waterMarkContainer.Click += new EventHandler(waterMarkContainer_Click);
            txt.Controls.Add(waterMarkContainer); // adds the control
        }
    }

    #endregion

    #region Eventhandlers

    #region WaterMark Events

    private void waterMarkContainer_Click(object sender, EventArgs e)
    {
        txt.Focus(); //Makes sure you can click wherever you want on the control to gain focus
    }

    private void waterMarkContainer_Paint(object sender, PaintEventArgs e)
    {
        //Setting the watermark container up
        waterMarkContainer.Location = new Point(WaterMarkPadding + 1, WaterMarkPadding); // sets the location
        waterMarkContainer.Height = txt.Height - 2 * WaterMarkPadding; // Height should be the same as its parent


        //
        waterMarkContainer.Anchor = AnchorStyles.Left | AnchorStyles.Right; // makes sure that it resizes with the parent control


        if (txt.ContainsFocus)
        {
            //if focused use normal color
            waterMarkBrush = new SolidBrush(this._waterMarkActiveColor);
        }

        else
        {
            //if not focused use not active color
            waterMarkBrush = new SolidBrush(this._waterMarkColor);
        }

        //Drawing the string into the panel 
        Graphics g = e.Graphics;
        g.DrawString(this._waterMarkText, waterMarkFont, waterMarkBrush, new PointF(-2f, 1f));//Take a look at that point
        //The reason I'm using the panel at all, is because of this feature, that it has no limits
        //I started out with a label but that looked very very bad because of its paddings 

        if (!WaterMarkAlwaysDisplay)
        {
            waterMarkContainer.Width = txt.Width - 2 * WaterMarkPadding - 1; // same goes for width and the parent
        }
        else
        {
            lbl.AutoSize = true;
            waterMarkContainer.AutoSize = true;
            waterMarkContainer.AutoSizeMode = AutoSizeMode.GrowAndShrink;
        }
    }

    #endregion

    #region CTextBox Events

    private void ThisHasFocus(object sender, EventArgs e)
    {
        //if focused use focus color
        waterMarkBrush = new SolidBrush(this._waterMarkActiveColor);

        //The watermark should not be drawn if the user has already written some text
        if (txt.TextLength <= 0)
        {
            //if (!WaterMarkAlwaysDisplay)
            //    RemoveWaterMark();
            DrawWaterMark();
            //txt.SetFocus_SelectAll();
        }
    }

    private void ThisWasLeaved(object sender, EventArgs e)
    {
        //if the user has written something and left the control
        if (txt.TextLength > 0)
        {
            //Remove the watermark if it not set is always display
            if (!WaterMarkAlwaysDisplay)
                RemoveWaterMark();
            //

        }
        else
        {
            //But if the user didn't write anything, Then redraw the control.
            DrawWaterMark();
            txt.Invalidate();
        }
    }

    private void ThisTextChanged(object sender, EventArgs e)
    {
        //If the text of the textbox is not empty
        if (txt.TextLength > 0)
        {
            //Remove the watermark
            if (!WaterMarkAlwaysDisplay)
                RemoveWaterMark();
            //
            //txt.Invalidate();
            txt.Focus();
            //txt.SelectionStart = txt.Text.Length;
        }
        else
        {
            //But if the text is empty, draw the watermark again.
            DrawWaterMark();
            txt.Invalidate();
            //txt.Focus();
        }
    }

    #region Overrided Events

    //protected override void OnPaint(PaintEventArgs e)
    //{
    //    base.OnPaint(e);
    //    //Draw the watermark even in design time
    //    DrawWaterMark();
    //}

    void txt_Validated(object sender, EventArgs e)
    {
        if (waterMarkContainer != null && !WaterMarkAlwaysDisplay)
            //if there is a watermark it should also be invalidated();
            waterMarkContainer.Invalidate();
    }


    #endregion

    #endregion

    #endregion

    #region Properties
    [Category("Watermark attribtues")]
    [Description("Sets the text of the watermark")]
    public string WaterMark
    {
        get { return this._waterMarkText; }
        set
        {
            this._waterMarkText = value;
            txt.Invalidate();
        }
    }

    [Category("Watermark attribtues")]
    [Description("When the control gaines focus, this color will be used as the watermark's forecolor")]
    public Color WaterMarkActiveForeColor
    {
        get { return this._waterMarkActiveColor; }

        set
        {
            this._waterMarkActiveColor = value;
            txt.Invalidate();
        }
    }

    [Category("Watermark attribtues")]
    [Description("When the control looses focus, this color will be used as the watermark's forecolor")]
    public Color WaterMarkForeColor
    {
        get { return this._waterMarkColor; }

        set
        {
            this._waterMarkColor = value;
            txt.Invalidate();
        }
    }

    [Category("Watermark attribtues")]
    [Description("The font used on the watermark. Default is the same as the control")]
    public Font WaterMarkFont
    {
        get
        {
            return this.waterMarkFont;
        }

        set
        {
            this.waterMarkFont = value;
            txt.Invalidate();
        }
    }

    [Category("Watermark attribtues")]
    [Description("The font used on the watermark. Default is the same as the control")]
    public int WaterMarkPadding
    {
        get
        {
            return this._waterMarkPadding;
        }

        set
        {
            this._waterMarkPadding = value;
            txt.Invalidate();
        }
    }


    [Category("Watermark attribtues")]
    [Description("Watermark always display")]
    public bool WaterMarkAlwaysDisplay
    {
        get;
        set;
    }

    #endregion
}

////Custom Control
//public class WaterMarkTextBox : TextBox
//{
//    #region Fields

//    #region Protected Fields

//    protected string _waterMarkText = "Default Watermark..."; //The watermark text
//    protected Color _waterMarkColor; //Color of the watermark when the control does not have focus
//    protected Color _waterMarkActiveColor; //Color of the watermark when the control has focus

//    #endregion

//    #region Private Fields

//    private Panel waterMarkContainer; //Container to hold the watermark
//    private Font waterMarkFont; //Font of the watermark
//    private SolidBrush waterMarkBrush; //Brush for the watermark

//    #endregion

//    #endregion

//    #region Constructors

//    public WaterMarkTextBox()
//    {
//        Initialize();
//    }

//    #endregion

//    #region Private Methods

//    /// <summary>
//    /// Initializes watermark properties and adds CtextBox events
//    /// </summary>
//    private void Initialize()
//    {
//        //Sets some default values to the watermark properties
//        _waterMarkColor = Color.LightGray;
//        _waterMarkActiveColor = Color.Gray;
//        waterMarkFont = this.Font;
//        waterMarkBrush = new SolidBrush(_waterMarkActiveColor);
//        waterMarkContainer = null;

//        //Draw the watermark, so we can see it in design time
//        DrawWaterMark();

//        //Eventhandlers which contains function calls. 
//        //Either to draw or to remove the watermark
//        this.Enter += new EventHandler(ThisHasFocus);
//        this.Leave += new EventHandler(ThisWasLeaved);
//        this.TextChanged += new EventHandler(ThisTextChanged);
//    }

//    /// <summary>
//    /// Removes the watermark if it should
//    /// </summary>
//    private void RemoveWaterMark()
//    {
//        if (waterMarkContainer != null)
//        {
//            this.Controls.Remove(waterMarkContainer);
//            waterMarkContainer = null;
//        }
//    }

//    /// <summary>
//    /// Draws the watermark if the text length is 0
//    /// </summary>
//    private void DrawWaterMark()
//    {
//        if (this.waterMarkContainer == null && this.TextLength <= 0)
//        {
//            waterMarkContainer = new Panel(); // Creates the new panel instance
//            waterMarkContainer.Paint += new PaintEventHandler(waterMarkContainer_Paint);
//            waterMarkContainer.Invalidate();
//            waterMarkContainer.Click += new EventHandler(waterMarkContainer_Click);
//            this.Controls.Add(waterMarkContainer); // adds the control
//        }
//    }

//    #endregion

//    #region Eventhandlers

//    #region WaterMark Events

//    private void waterMarkContainer_Click(object sender, EventArgs e)
//    {
//        this.Focus(); //Makes sure you can click wherever you want on the control to gain focus
//    }

//    private void waterMarkContainer_Paint(object sender, PaintEventArgs e)
//    {
//        //Setting the watermark container up
//        waterMarkContainer.Location = new Point(2, 0); // sets the location
//        waterMarkContainer.Height = this.Height; // Height should be the same as its parent
//        waterMarkContainer.Width = this.Width; // same goes for width and the parent
//        waterMarkContainer.Anchor = AnchorStyles.Left | AnchorStyles.Right; // makes sure that it resizes with the parent control



//        if (this.ContainsFocus)
//        {
//            //if focused use normal color
//            waterMarkBrush = new SolidBrush(this._waterMarkActiveColor);
//        }

//        else
//        {
//            //if not focused use not active color
//            waterMarkBrush = new SolidBrush(this._waterMarkColor);
//        }

//        //Drawing the string into the panel 
//        Graphics g = e.Graphics;
//        g.DrawString(this._waterMarkText, waterMarkFont, waterMarkBrush, new PointF(-2f, 1f));//Take a look at that point
//        //The reason I'm using the panel at all, is because of this feature, that it has no limits
//        //I started out with a label but that looked very very bad because of its paddings 

//    }

//    #endregion

//    #region CTextBox Events

//    private void ThisHasFocus(object sender, EventArgs e)
//    {
//        //if focused use focus color
//        waterMarkBrush = new SolidBrush(this._waterMarkActiveColor);

//        //The watermark should not be drawn if the user has already written some text
//        if (this.TextLength <= 0)
//        {
//            RemoveWaterMark();
//            DrawWaterMark();
//        }
//    }

//    private void ThisWasLeaved(object sender, EventArgs e)
//    {
//        //if the user has written something and left the control
//        if (this.TextLength > 0)
//        {
//            //Remove the watermark
//            RemoveWaterMark();
//        }
//        else
//        {
//            //But if the user didn't write anything, Then redraw the control.
//            this.Invalidate();
//        }
//    }

//    private void ThisTextChanged(object sender, EventArgs e)
//    {
//        //If the text of the textbox is not empty
//        if (this.TextLength > 0)
//        {
//            //Remove the watermark
//            RemoveWaterMark();
//        }
//        else
//        {
//            //But if the text is empty, draw the watermark again.
//            DrawWaterMark();
//        }
//    }

//    #region Overrided Events

//    protected override void OnPaint(PaintEventArgs e)
//    {
//        base.OnPaint(e);
//        //Draw the watermark even in design time
//        DrawWaterMark();
//    }

//    protected override void OnInvalidated(InvalidateEventArgs e)
//    {
//        base.OnInvalidated(e);
//        //Check if there is a watermark
//        if (waterMarkContainer != null)
//            //if there is a watermark it should also be invalidated();
//            waterMarkContainer.Invalidate();
//    }

//    #endregion

//    #endregion

//    #endregion

//    #region Properties
//    [Category("Watermark attribtues")]
//    [Description("Sets the text of the watermark")]
//    public string WaterMark
//    {
//        get { return this._waterMarkText; }
//        set
//        {
//            this._waterMarkText = value;
//            this.Invalidate();
//        }
//    }

//    [Category("Watermark attribtues")]
//    [Description("When the control gaines focus, this color will be used as the watermark's forecolor")]
//    public Color WaterMarkActiveForeColor
//    {
//        get { return this._waterMarkActiveColor; }

//        set
//        {
//            this._waterMarkActiveColor = value;
//            this.Invalidate();
//        }
//    }

//    [Category("Watermark attribtues")]
//    [Description("When the control looses focus, this color will be used as the watermark's forecolor")]
//    public Color WaterMarkForeColor
//    {
//        get { return this._waterMarkColor; }

//        set
//        {
//            this._waterMarkColor = value;
//            this.Invalidate();
//        }
//    }

//    [Category("Watermark attribtues")]
//    [Description("The font used on the watermark. Default is the same as the control")]
//    public Font WaterMarkFont
//    {
//        get
//        {
//            return this.waterMarkFont;
//        }

//        set
//        {
//            this.waterMarkFont = value;
//            this.Invalidate();
//        }
//    }

//    #endregion
//}

